package com.share.ai.langchain4j.config;

import com.share.ai.langchain4j.functioncalls.Tools;
import dev.langchain4j.community.model.dashscope.QwenChatModel;
import dev.langchain4j.community.model.dashscope.QwenStreamingChatModel;
import dev.langchain4j.memory.chat.ChatMemoryProvider;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.ollama.OllamaChatModel;
import dev.langchain4j.model.ollama.OllamaStreamingChatModel;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.service.AiServices;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

/**
 * 对话实现记忆的核心思路 ： 这里本质上是动态代理，拦截请求和响应的参数，在每次请求模型时,要把历史所有的 请求和响应按顺序再发送给ai
 * MessageWindowChatMemory 是内存的默认 应该放入redis更好
 * <p>
 * <p>
 * Bean的名称默认是@Bean方法的方法名，也可以通过@Bean注解显式指定
 * 在参数名无法匹配时，使用@Qualifier注解显式指定Bean名称。
 *
 * <p>
 * 创建内存储存对象
 * MessageWindowChatMemory memory = MessageWindowChatMemory.withMaxMessages(MEMORY_RECORD_MAX);
 */
@Configuration
public class MemoryReqAndRspConfig {
    //设置记忆的大小
    private final static int MEMORY_RECORD_MAX = 100;

    //ollamaChatAssistant 使用内存记忆
    //bean注解 支持参数自动注入
    @Bean
    public ChatAssistant ollamaChatAssistant(OllamaChatModel ollamaChatModel,
                                             OllamaStreamingChatModel ollamaStreamingChatModel, List<Tools> toolsList,ContentRetriever contentRetriever) {
        //使用内存记忆
//        MessageWindowChatMemory memory = MessageWindowChatMemory.withMaxMessages(MEMORY_RECORD_MAX);
//        ChatAssistant定义了memoryId因此只能用第二个方法.chatMemoryProvider(chatMemoryProvider)
        ChatMemoryProvider chatMemoryProvider = memoryId -> MessageWindowChatMemory.builder()
                .maxMessages(MEMORY_RECORD_MAX)
                .id(memoryId)
                .build();


        return AiServices.builder(ChatAssistant.class)
                .chatModel(ollamaChatModel)
                .streamingChatModel(ollamaStreamingChatModel)
                .tools(toolsList) //function-call
                .contentRetriever(contentRetriever) //检索增强
//                .chatMemory(memory)
                .chatMemoryProvider(chatMemoryProvider)  //上下文存储器
                .build();
    }

    //qwenChatAssistant  使用自定义存储
    //@bean注解 支持参数自动注入
    @Bean
    public ChatAssistant qwenChatAssistant(QwenChatModel qwenChatModel, QwenStreamingChatModel qwenStreamingChatModel, List<Tools> toolsList, ContentRetriever contentRetriever, PersistentChatMemoryStore persistentChatMemoryStore) {
        //使用自定义存储
        ChatMemoryProvider chatMemoryProvider = memoryId -> MessageWindowChatMemory.builder()
                .maxMessages(MEMORY_RECORD_MAX)
                .id(memoryId)
                .chatMemoryStore(persistentChatMemoryStore)
                .build();

        return AiServices.builder(ChatAssistant.class)
                .chatModel(qwenChatModel)
                .streamingChatModel(qwenStreamingChatModel)
                .tools(toolsList) //function-call
                .contentRetriever(contentRetriever) //检索增强
                .chatMemoryProvider(chatMemoryProvider) //上下文存储器
                .build();
    }
}
